/*
 * RISC-V 中断和异常相关寄存器操作
 * 扩展基本的RISC-V寄存器定义，专注于中断处理
 */

#ifndef RISCV_REGS_H
#define RISCV_REGS_H

#include "../fs/types.h"
#include "../mm/riscv.h"

// sstatus寄存器位定义
#define SSTATUS_SPP (1L << 8)  // Previous mode, 1=Supervisor, 0=User
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
#define SSTATUS_SIE (1L << 1)  // Supervisor Interrupt Enable
#define SSTATUS_UIE (1L << 0)  // User Interrupt Enable

// sie寄存器位定义
#define SIE_SEIE (1L << 9) // supervisor external interrupt
#define SIE_UEIE (1L << 8) // user external interrupt
#define SIE_STIE (1L << 5) // supervisor timer interrupt
#define SIE_UTIE (1L << 4) // user timer interrupt
#define SIE_SSIE (1L << 1) // supervisor software interrupt
#define SIE_USIE (1L << 0) // user software interrupt

// sip寄存器位定义
#define SIP_SEIP (1L << 9) // supervisor external interrupt pending
#define SIP_UEIP (1L << 8) // user external interrupt pending
#define SIP_STIP (1L << 5) // supervisor timer interrupt pending
#define SIP_UTIP (1L << 4) // user timer interrupt pending
#define SIP_SSIP (1L << 1) // supervisor software interrupt pending
#define SIP_USIP (1L << 0) // user software interrupt pending

// mstatus寄存器位定义
#define MSTATUS_MPP_MASK (3L << 11) // previous mode.
#define MSTATUS_MPP_M (3L << 11)
#define MSTATUS_MPP_S (1L << 11)
#define MSTATUS_MPP_U (0L << 11)
#define MSTATUS_MIE (1L << 3)    // machine-mode interrupt enable.

// mie寄存器位定义
#define MIE_MEIE (1L << 11) // machine external interrupt enable
#define MIE_SEIE (1L << 9)  // supervisor external interrupt enable
#define MIE_UEIE (1L << 8)  // user external interrupt enable
#define MIE_MTIE (1L << 7)  // machine timer interrupt enable
#define MIE_STIE (1L << 5)  // supervisor timer interrupt enable
#define MIE_UTIE (1L << 4)  // user timer interrupt enable
#define MIE_MSIE (1L << 3)  // machine software interrupt enable
#define MIE_SSIE (1L << 1)  // supervisor software interrupt enable
#define MIE_USIE (1L << 0)  // user software interrupt enable

// 读取CSR寄存器的宏
#define r_sstatus() ({ \
    uint64 x; \
    asm volatile("csrr %0, sstatus" : "=r" (x)); \
    x; \
})

#define r_sie() ({ \
    uint64 x; \
    asm volatile("csrr %0, sie" : "=r" (x)); \
    x; \
})

#define r_sip() ({ \
    uint64 x; \
    asm volatile("csrr %0, sip" : "=r" (x)); \
    x; \
})

#define r_scause() ({ \
    uint64 x; \
    asm volatile("csrr %0, scause" : "=r" (x)); \
    x; \
})

#define r_sepc() ({ \
    uint64 x; \
    asm volatile("csrr %0, sepc" : "=r" (x)); \
    x; \
})

#define r_stval() ({ \
    uint64 x; \
    asm volatile("csrr %0, stval" : "=r" (x)); \
    x; \
})

#define r_stvec() ({ \
    uint64 x; \
    asm volatile("csrr %0, stvec" : "=r" (x)); \
    x; \
})

#define r_time() ({ \
    uint64 x; \
    asm volatile("csrr %0, time" : "=r" (x)); \
    x; \
})

#define r_mhartid() ({ \
    uint64 x; \
    asm volatile("csrr %0, mhartid" : "=r" (x)); \
    x; \
})

// 写入CSR寄存器的宏
#define w_sstatus(x) asm volatile("csrw sstatus, %0" : : "r" (x))
#define w_sie(x) asm volatile("csrw sie, %0" : : "r" (x))
#define w_sip(x) asm volatile("csrw sip, %0" : : "r" (x))
#define w_sepc(x) asm volatile("csrw sepc, %0" : : "r" (x))
#define w_stvec(x) asm volatile("csrw stvec, %0" : : "r" (x))

// Machine模式寄存器操作
#define r_mstatus() ({ \
    uint64 x; \
    asm volatile("csrr %0, mstatus" : "=r" (x)); \
    x; \
})

#define r_mie() ({ \
    uint64 x; \
    asm volatile("csrr %0, mie" : "=r" (x)); \
    x; \
})

#define r_mip() ({ \
    uint64 x; \
    asm volatile("csrr %0, mip" : "=r" (x)); \
    x; \
})

#define w_mstatus(x) asm volatile("csrw mstatus, %0" : : "r" (x))
#define w_mie(x) asm volatile("csrw mie, %0" : : "r" (x))
#define w_mtvec(x) asm volatile("csrw mtvec, %0" : : "r" (x))
#define w_mepc(x) asm volatile("csrw mepc, %0" : : "r" (x))
#define w_medeleg(x) asm volatile("csrw medeleg, %0" : : "r" (x))
#define w_mideleg(x) asm volatile("csrw mideleg, %0" : : "r" (x))

// 中断控制函数
static inline void intr_on(void)
{
    w_sstatus(r_sstatus() | SSTATUS_SIE);
}

static inline void intr_off(void)
{
    w_sstatus(r_sstatus() & ~SSTATUS_SIE);
}

static inline int intr_get(void)
{
    uint64 x = r_sstatus();
    return (x & SSTATUS_SIE) != 0;
}

// SBI调用相关
#define SBI_SET_TIMER 0
#define SBI_CONSOLE_PUTCHAR 1
#define SBI_CONSOLE_GETCHAR 2
#define SBI_CLEAR_IPI 3
#define SBI_SEND_IPI 4
#define SBI_REMOTE_FENCE_I 5
#define SBI_REMOTE_SFENCE_VMA 6
#define SBI_REMOTE_SFENCE_VMA_ASID 7
#define SBI_SHUTDOWN 8

// SBI调用函数
static inline uint64 sbi_call(uint64 which, uint64 arg0, uint64 arg1, uint64 arg2)
{
    register uint64 a0 asm ("a0") = arg0;
    register uint64 a1 asm ("a1") = arg1;
    register uint64 a2 asm ("a2") = arg2;
    register uint64 a7 asm ("a7") = which;
    asm volatile ("ecall"
                  : "+r" (a0)
                  : "r" (a1), "r" (a2), "r" (a7)
                  : "memory");
    return a0;
}

// 设置时钟中断
static inline void sbi_set_timer(uint64 time)
{
    sbi_call(SBI_SET_TIMER, time, 0, 0);
}

#endif // RISCV_REGS_H